using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using SpaceShooter.Utilities;


namespace SpaceShooter.Components
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class PowerUpManager : Microsoft.Xna.Framework.GameComponent
    {
        public static StateManagement.GameState gs;
        static PlayerComponent player;

        public PowerUpManager(Game game)
            : base(game)
        {
            gs = (StateManagement.GameState)Game.Services.GetService(typeof(StateManagement.GameState));
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here
            //Game.Services.AddService(typeof(LinkedList<PowerUp>), gs.powerUps);
            player = (PlayerComponent)Game.Services.GetService(typeof (PlayerComponent));
            base.Initialize();
        }

        protected override void Dispose(bool disposing)
        {
            //Game.Services.RemoveService(typeof(List<PowerUp>));
            base.Dispose(disposing);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            if (!gs.pause)
            {
                // TODO: Add your update code here
                PowerUp[] temp = new PowerUp[gs.powerUps.Count];
                int i = 0;

                //Aggiorna tutte le istanze della classe PowerUp presenti nella lista
                foreach (PowerUp x in gs.powerUps)
                {
                    if (!gs.timeTraveling)
                        x.Update();
                    else
                        x.TimeTravel();

                    if (x.delete)
                    {
                        temp[i] = x;
                        i++;
                    }
                }

                //Elimina le istanze della classe PowerUp che hanno terminato il loro ciclo di vita
                for (i = 0; i < temp.Length && temp[i] != null; i++)
                {
                    gs.powerUps.Remove(temp[i]);
                }

            }
            base.Update(gameTime);
        }

        /// <summary>
        /// Handler per evento di nuovo PowerUp
        /// </summary>
        public void OnNewPowerUp(Vector2 Position, PowerUpType Type)
        {
            gs.powerUps.AddFirst(new PowerUp(Position, Type));
        }

        #region PowerUp

        /// <summary>
        /// Definisce un singolo oggetto fumo.
        /// </summary>
        public class PowerUp
        {
            private LinkedList<PowerUpState> states;
            public int deathCounter;
            public Vector2 pos;
            public bool delete;
            public LifeState lifeState;
            public PowerUpType Type;
            public Vector2 Position
            {
                get
                {
                    return pos;
                }
            }

            public LinkedList<PowerUpState> GetStates()
            {
                return states;
            }
            public void SetStates(PowerUpState[] newStates)
            {
                states = new LinkedList<PowerUpState>(newStates);
            }

            public PowerUp() { }

            /// <summary>
            /// Istanzia un oggetto PowerUp con posizione Position
            /// </summary>
            /// <param name="Position">La posizione del fumo sullo schermo</param>
            public PowerUp(Vector2 Position, PowerUpType PowerUpType)
            {
                Type = PowerUpType;
                pos = Position;
                delete = false;
                lifeState = LifeState.NORMAL;
                states = new LinkedList<PowerUpState>();
                deathCounter = 0;
            }

            /// <summary>
            /// Aggiorna lo stato del PowerUp.
            /// </summary>
            public void Update()
            {
                if (lifeState != LifeState.DEAD)
                {
                    pos.Y += 3;
                    states.AddFirst(new PowerUpState(new Vector2(Position.X, Position.Y), lifeState));
                    if (states.Count > gs.timeTank + 1)
                    {
                        states.RemoveLast();
                    }
                    if (!Utility.IsInScreenSpace(Utility.newRectangleFromCenterPosition(pos, 20, 20)))
                        lifeState = LifeState.DEAD;
                }
                else
                {
                    if (states.Count > 0)
                    {
                        if (states.Count + deathCounter > gs.timeTank)
                            states.RemoveLast();
                    }
                    else
                    {
                        delete = true;
                    }
                    deathCounter++;
                }
            }

            public void TimeTravel()
            {
                if (states.Count > 0)
                {
                    if (deathCounter > 0)
                        deathCounter--;
                    else
                    {
                        PowerUpState st = states.First.Value;
                        pos = st.pos;
                        lifeState = st.lifeState;
                        states.RemoveFirst();
                    }
                }
                else
                {
                    delete = true;
                }
            }
        }
        #endregion

        #region PowerUpState
        public class PowerUpState
        {
            public Vector2 pos;
            public LifeState lifeState;

            public PowerUpState() { }

            public PowerUpState(Vector2 Position, LifeState LifeState)
            {
                pos = Position;
                lifeState = LifeState;
            }
        }
        #endregion
    }
}
